package com.hopes.bizz.enforcement.hid.bo;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.hopes.bizz.common.core.util.StringUtils;

import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author yumr
 * @ProjectName bizz
 * @Description 根据计划周期获取计划时间
 * @time 2023/8/17 15:18
 */
public class HidPlanCycleDateBO {

    private static final String PLAN_PUSH_CYCLE_YEAR = "3";//计划-推送周期-年
    private static final String PLAN_PUSH_CYCLE_MONTH = "2";//计划-推送周期-月
    private static final String PLAN_PUSH_CYCLE_WEEK = "1";//计划-推送周期-周
    // 周期
    private final String cycle;

    private final String dates;

    private final String hours;


    public HidPlanCycleDateBO(String cycle, String dates, String hours) {
        this.cycle = cycle;
        this.dates = dates;
        this.hours = hours;
    }

    public Date getPlanDate() {
        if (StringUtils.isEmpty(cycle) || StringUtils.isEmpty(dates) || StringUtils.isEmpty(hours)) {
            return null;
        }
        List<Integer> dateList = Stream.of(dates.split(",")).map(Integer::valueOf).sorted().collect(Collectors.toList());
        List<Integer> hourList = Stream.of(hours.split(",")).map(Integer::valueOf).sorted().collect(Collectors.toList());
        switch (cycle) {
            case PLAN_PUSH_CYCLE_YEAR:
                return getCloseDateIfCycleIsYear(dateList, hourList);
            case PLAN_PUSH_CYCLE_MONTH:
                return getCloseDateIfCycleIsMonth(dateList, hourList);
            case PLAN_PUSH_CYCLE_WEEK:
                return getCloseDateIfCycleIsWeek(dateList, hourList);
            default:
                return null;
        }
    }

    private Date getCloseDateIfCycleIsWeek(List<Integer> dateList, List<Integer> hourList) {
        LocalDateTime now = LocalDateTime.now();
        int nowDay = now.getDayOfWeek().getValue();
        int nowHour = now.getHour();
        //过滤大于当前日期的时间
        List<Integer> gtNowDayList = dateList.stream().filter(day -> day >= nowDay).sorted().collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(gtNowDayList)) {
            for (Integer day : gtNowDayList) {
                for (Integer hour : hourList) {
                    if (day == nowDay) {
                        if (hour > nowHour) {
                            return DateUtil.date(LocalDateTime.now().withHour(hour).withMinute(0).withSecond(0));
                        }
                    } else {
                        return DateUtil.date(LocalDateTime.now().plusDays(day - nowDay).withHour(hour).withMinute(0).withSecond(0));
                    }
                }
            }
        }
        //都小于当前日 或者等于
        Integer nearDay = dateList.get(0);
        Integer nearHour = hourList.get(0);
        return DateUtil.date(LocalDateTime.now().plusDays(7 - nowDay + nearDay).withHour(nearHour).withMinute(0).withSecond(0));
    }

    private Date getCloseDateIfCycleIsMonth(List<Integer> dateList, List<Integer> hourList) {
        LocalDateTime now = LocalDateTime.now();
        int nowDay = now.getDayOfMonth();
        int nowHour = now.getHour();
        //当前月共有多少天
        int countDayOfMonth = now.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();

        List<Integer> gtNowDayList = dateList.stream().filter(day -> day >= nowDay).sorted().collect(Collectors.toList());

        if (CollectionUtil.isNotEmpty(gtNowDayList)) {
            for (Integer day : gtNowDayList) {
                for (Integer hour : hourList) {
                    if (day == nowDay) {
                        if (hour > nowHour) {
                            return DateUtil.date(LocalDateTime.now().withHour(hour).withMinute(0).withSecond(0));
                        }
                    } else {
                        return DateUtil.date(LocalDateTime.now().plusDays(day - nowDay).withHour(hour).withMinute(0).withSecond(0));
                    }
                }
            }
        }
        //都小于当前日 或者等于
        Integer nearDay = dateList.get(0);
        Integer nearHour = hourList.get(0);
        return DateUtil.date(LocalDateTime.now().plusDays(countDayOfMonth - nowDay + nearDay).withHour(nearHour).withMinute(0).withSecond(0));
    }

    private Date getCloseDateIfCycleIsYear(List<Integer> pushMonth, List<Integer> hourList) {
        LocalDateTime now = LocalDateTime.now();
        int nowMonth = now.getMonthValue();
        int nowHour = now.getHour();
        int nowDay = now.getDayOfMonth();

        List<Integer> gtNowMonthList = pushMonth.stream().filter(month -> month > nowMonth || (month == nowMonth && nowDay == 1)).sorted().collect(Collectors.toList());

        if (CollectionUtil.isNotEmpty(gtNowMonthList)) {
            for (Integer month : gtNowMonthList) {
                for (Integer hour : hourList) {
                    if (month == nowMonth) {
                        if (hour > nowHour) {
                            return DateUtil.date(LocalDateTime.now().withHour(hour).withMinute(0).withSecond(0));
                        }
                    } else {
                        return DateUtil.date(LocalDateTime.now().plusMonths(month - nowMonth).withDayOfMonth(1).withHour(hour).withMinute(0).withSecond(0));
                    }
                }
            }
        }
        //都小于当前日 或者等于
        Integer nearMonth = pushMonth.get(0);
        Integer nearHour = hourList.get(0);
        return DateUtil.date(LocalDateTime.now().plusMonths(12 - nowMonth + nearMonth).withDayOfMonth(1).withHour(nearHour).withMinute(0).withSecond(0));
    }

}
